In [1]:
import ipynb.fs.full.features as features
In [2]:
from sklearn import preprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin_min

%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')
In [3]:
# df_train = pd.read_csv('./data/train.csv')
df_train = pd.read_csv('./data/train_filtrado.csv')
df_aux_train = df_train

df_test = pd.read_csv('./data/test.csv')
df_aux_test = df_test
In [4]:
df_aux_train
Out[4]:
id titulo descripcion tipodepropiedad direccion ciudad provincia antiguedad habitaciones garages ... idzona lat lng fecha gimnasio usosmultiples piscina escuelascercanas centroscomercialescercanos precio
0 254099 depto. tipo a-402 depto. interior de 80.15m2, consta de sala com... Apartamento Avenida Division del Norte 2005 Benito Juárez Distrito Federal 8.142306 2.0 1.0 ... 23533.0 19.365745 -99.159964 2015-08-23 00:00:00 0.0 0.0 0.0 0.0 0.0 2273000.0
1 53461 condominio horizontal en venta <p>entre sonora y guerrero, atr&aacute;s del h... Casa en condominio AV. MEXICO La Magdalena Contreras Distrito Federal 10.000000 3.0 2.0 ... 24514.0 19.310205 -99.227655 2013-06-28 00:00:00 0.0 0.0 0.0 1.0 1.0 3600000.0
2 247984 casa en venta urbi 3 recamaras tonala descripcion \nla mejor ubicacion residencial e... Casa Urbi Tonala Tonalá Jalisco 5.000000 3.0 2.0 ... 48551.0 20.667955 -103.212654 2015-10-17 00:00:00 0.0 0.0 0.0 0.0 0.0 1200000.0
3 209067 casa sola en toluca zinacantepec con credito i... casa en privada con caseta de vigilancia casas... Casa IGNACIO MANUEL ALTAMIRANO 128 Zinacantepec Edo. de México 1.000000 2.0 1.0 ... 53666.0 19.301890 -99.688015 2012-03-09 00:00:00 0.0 0.0 0.0 1.0 1.0 650000.0
4 185997 paseos del sol bonito departamento en excelentes condiciones ... Apartamento PASEOS DEL SOL Zapopan Jalisco 10.000000 2.0 1.0 ... 47835.0 20.638654 -103.433251 2016-06-07 00:00:00 0.0 0.0 0.0 0.0 0.0 1150000.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
236298 119879 bonita casas de 2 recamaras a 10 minutos del c... vendo casa en bosques de ica residencial a 10 ... Casa BOSQUES Zinacantepec Edo. de México 0.000000 2.0 2.0 ... 53666.0 19.337865 -99.649164 2015-02-08 00:00:00 0.0 0.0 0.0 0.0 0.0 650000.0
236299 259178 casa en condominio a 10 min. del centro de toluca casa con un jardin amplio, un cuarto de servic... Casa Filiberto Navas 325 Toluca Edo. de México 0.000000 3.0 3.0 ... 51954.0 19.294665 -99.692916 2014-07-10 00:00:00 0.0 0.0 0.0 1.0 1.0 1940000.0
236300 131932 nicolas san juan departamento con excelente ubicación, muy cerc... Apartamento Nicolas San Juan Benito Juárez Distrito Federal 20.000000 2.0 1.0 ... 50003995.0 19.389344 -99.175172 2015-03-03 00:00:00 0.0 0.0 0.0 0.0 0.0 3400000.0
236301 146867 casa sola. javier rojo gomez. casa sola, dividida en cuatro departamentos de... Casa Javier Rojo Gomez 120 Iztapalapa Distrito Federal 20.000000 4.0 0.0 ... 24162.0 19.366651 -99.082246 2014-12-26 00:00:00 1.0 0.0 0.0 1.0 1.0 2890000.0
236302 121958 departamento en bosques de las lomas / av. st... id:19816, muy bonito e iluminado departamento,... Apartamento AVE. STIM Cuajimalpa de Morelos Distrito Federal 1.000000 3.0 2.0 ... 23750.0 19.388850 -99.263321 2015-06-19 00:00:00 0.0 0.0 0.0 0.0 0.0 3650000.0

236303 rows × 23 columns

In [5]:
# Normalizacion

def _normalizacion(df, columnas):
    x = df.values #returns a numpy array
    min_max_scaler = preprocessing.MinMaxScaler()
    x_scaled = min_max_scaler.fit_transform(x)
    df = pd.DataFrame(x_scaled)
    df.columns = columnas
    return df
In [6]:
def generar_grafico(df_completo, columnas, df_y=[]):
    """ df_completo: El df a calcular kmeans
        columnas: Es con que columnas se va a calcular
        df_y es la columna precio (es una serie)"""
    """Muestra el grafico de variacion entre 0 y 20 clusters(k)"""
    """Retorna X e y, para usar en el entrenamiento y la clasificacion"""
    df = df_completo[columnas].copy()
    for columna in columnas:
        df[columna] = df[columna].fillna(df[columna].mean())
    df = _normalizacion(df, columnas)
    
    X = np.array(df[columnas])
    y = None if type(df_y) == list else np.array(df_y)
    
    Nc = range(1, 20)
    kmeans = [KMeans(n_clusters=i) for i in Nc]
    score = [kmeans[i].fit(X).score(X) for i in range(len(kmeans))]

    plt.figure(figsize=(15,15))
    plt.plot(Nc,score)
    plt.xlabel('Number of Clusters')
    plt.ylabel('Score')
    plt.title('Elbow Curve')
    plt.show()
    
    return df, X, y
In [7]:
def etiquetado(k_cluster, X):
    # k Max es el largo de este arreglo
    colores=['red','green','blue','cyan','yellow', 'black', 'brown', 'orange', 'pink', 'purple', 'beige']
    kmeans = KMeans(n_clusters=k_cluster).fit(X)
    colores = colores[:k_cluster]
    # Clasificacion
    labels = kmeans.predict(X)
    C = kmeans.cluster_centers_ # Centroides
    asignar = []
    for row in labels:
        asignar.append(colores[row])
    # Grafico de todos los puntos clasificados:    
    if X.shape[1] > 2:
        fig = plt.figure(figsize=(20,20))
        ax = Axes3D(fig)
        ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=asignar,s=60)
        ax.scatter(C[:, 0], C[:, 1], C[:, 2], marker='*', c=colores, s=1000)
    return labels, asignar, X, C, colores
In [8]:
def proyeccion_2d(df, col1, col2, asignar, C, colores, fig_size=(20, 20)):
    f1 = df[col1].values
    f2 = df[col2].values

    plt.figure(figsize=fig_size)
    plt.scatter(f1, f2, c=asignar, s=70)
    plt.scatter(C[:, 0], C[:, 1], marker='*', c=colores, s=1000)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.show()
In [9]:
def generar_csv_final(ids_series, labels, colores):
    final =  pd.DataFrame()
    # final['id'] = df_aux['id'].values
    final['id'] = ids_series.values
    final['label'] = labels;
    cantidadGrupo =  pd.DataFrame()
    cantidadGrupo['color'] = colores
    cantidadGrupo['cantidad'] = final.groupby('label').size()
    display(cantidadGrupo)
    return final

Features Básicos

Con el set de entrenamiento

In [10]:
columnas_basicas = ['metroscubiertos', 'metrostotales', 'antiguedad', 'habitaciones', 'garages', 'banos',
            'lat', 'lng', 'escuelascercanas', 'centroscomercialescercanos']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_basicas, df_precio)
In [11]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [12]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [13]:
proyeccion_2d(df_train, 'antiguedad', 'metrostotales', asignar, C, colores)
In [14]:
ids_series = df_aux_train['id']
final_train_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_basicas = final_train_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 70882
1 green 35693
2 blue 51124
3 cyan 18351
4 yellow 53125
5 black 7128

Con el set de testeo

In [15]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_basicas)
In [16]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [17]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [18]:
proyeccion_2d(df_test, 'antiguedad', 'metrostotales', asignar, C, colores)
In [19]:
ids_series = df_aux_test['id']
final_test_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_basicas = final_test_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 13235
1 green 8940
2 blue 18184
3 cyan 4655
4 yellow 13163
5 black 1823

Features Dependientes de la superficie

Set de entrenamiento

In [20]:
columnas_superficie = ['metroscubiertos', 'metrostotales']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_superficie, df_precio)
In [21]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [22]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [23]:
ids_series = df_aux_train['id']
final_train_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_train_columnas_superficie = final_train_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 29815
1 green 51573
2 blue 7563
3 cyan 13136
4 yellow 24153
5 black 17840
6 brown 44108
7 orange 48115

Set de testeo

In [24]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_superficie)
In [25]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [26]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [27]:
ids_series = df_aux_test['id']
final_test_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_test_columnas_superficie = final_test_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 7600
1 green 12029
2 blue 4468
3 cyan 9191
4 yellow 4023
5 black 3717
6 brown 8712
7 orange 10260

Features por metros totales cubiertos

Set de Entrenamiento

In [28]:
def metros_totales_cubiertos(df):
    punto20 = df_train['metrostotales'].quantile(0.2)
    punto40 = df_train['metrostotales'].quantile(0.4)
    punto60 = df_train['metrostotales'].quantile(0.6)
    punto80 = df_train['metrostotales'].quantile(0.8)
    punto20_cubiertos = df_train['metroscubiertos'].quantile(0.2)
    punto40_cubiertos = df_train['metroscubiertos'].quantile(0.4)
    punto60_cubiertos = df_train['metroscubiertos'].quantile(0.6)
    punto80_cubiertos = df_train['metroscubiertos'].quantile(0.8)
    df['metrostotales'] = df['metrostotales'].fillna(df['metroscubiertos'])
    df['metroscubiertos'] = df['metroscubiertos'].fillna(df['metrostotales'])
    df['metrostotales_log'] = np.log(df['metrostotales'])
    df['metroscubiertos_log'] = np.log(df['metroscubiertos'])
    df['porcentaje_metros'] = df['metroscubiertos']/df['metrostotales']
    df['diferencia_metros'] = df['metrostotales'] - df['metroscubiertos']
    df['intervalo_metros_totales'] = features.map_values(df['metrostotales'].values, lambda x: 1 if x<punto20 else (2 if punto20<x<punto40 else (3 if punto40<x<punto60 else(4 if punto60<x<punto80 else 5))))
    df['intervalo_metros_cubiertos'] = features.map_values(df['metroscubiertos'].values, lambda x: 1 if x<punto20_cubiertos else (2 if punto20_cubiertos<x<punto40_cubiertos else (3 if punto40_cubiertos<x<punto60_cubiertos else(4 if punto60_cubiertos<x<punto80_cubiertos else 5))))
    df['metroscubiertos_bins_unif'] = features.generar_intervalos_unif(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_perc'] = features.generar_intervalos_perc(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_unif'] = df['metroscubiertos_bins_unif'].astype(int)
    df['metroscubiertos_bins_perc'] = df['metroscubiertos_bins_perc'].astype(int)
    return df
In [29]:
df = df_aux_train.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos, df_precio)
In [30]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [31]:
proyeccion_2d(df_train, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [32]:
ids_series = df['id']
final_train_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_train_columnas_metros_cubiertos = final_train_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 48476
1 green 33669
2 blue 55582
3 cyan 26255
4 yellow 17677
5 black 54644

Set de testeo

In [33]:
df = df_aux_test.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_test, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos)
In [34]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [35]:
proyeccion_2d(df_test, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [36]:
ids_series = df['id']
final_test_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_test_columnas_metros_cubiertos = final_test_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 2875
1 green 13301
2 blue 10410
3 cyan 11925
4 yellow 7092
5 black 14397

Por fecha

Para el set de entrenamiento

In [37]:
def generar_features_fecha(df):
    df['fecha'] = pd.to_datetime(df['fecha'])
    df['anio'] = df['fecha'].dt.year
    df['mes'] = df['fecha'].dt.month
    df['dia'] = df['fecha'].dt.day
    df['trimestre'] = (df['fecha'].dt.month)%3+1
    df['delta_desde_datos'] = (df['fecha'] - df['fecha'].min())
    df['dias_desde_datos'] = df['delta_desde_datos'].dt.days
    df['meses_desde_datos'] = df['dias_desde_datos'] // 30   # Mas o menos...
    df.pop('delta_desde_datos')
    df['fecha'] = df['fecha'].astype(int)
    return df
In [38]:
df = df_aux_train.copy()
df = generar_features_fecha(df)

columnas_por_fecha = ['fecha', 'anio', 'mes', 'dia', 'trimestre', 'dias_desde_datos', 'meses_desde_datos' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_por_fecha, df_precio)
In [39]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [40]:
proyeccion_2d(df_train, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [41]:
ids_series = df['id']
final_train_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_fechas = final_train_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 19698
1 green 27194
2 blue 25109
3 cyan 25378
4 yellow 18218
5 black 20784
6 brown 20780
7 orange 18341
8 pink 20060
9 purple 19281
10 beige 21460

Para el set de testeo

In [42]:
df = df_aux_test.copy()
df = generar_features_fecha(df)

df_test, X, Y = generar_grafico(df, columnas_por_fecha)
In [43]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [44]:
proyeccion_2d(df_test, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [45]:
ids_series = df['id']
final_test_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_fechas = final_test_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 4367
1 green 5726
2 blue 6273
3 cyan 7508
4 yellow 4854
5 black 5220
6 brown 3960
7 orange 4055
8 pink 5716
9 purple 5600
10 beige 6721

Features Por latitud y longitud

Set de entrenamiento

In [46]:
columnas_lat_lng = ['lat', 'lng']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_lat_lng, df_precio)
In [47]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [48]:
proyeccion_2d(df_train, 'lat', 'lng', asignar, C, colores)
In [49]:
ids_series = df_aux_train['id']
final_train_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_train_columnas_latlng = final_train_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 3254
1 green 131667
2 blue 19227
3 cyan 23804
4 yellow 12547
5 black 7468
6 brown 32775
7 orange 5561

Para el set de test

In [50]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_lat_lng)
In [51]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [52]:
proyeccion_2d(df_test, 'lat', 'lng', asignar, C, colores)
In [53]:
ids_series = df_aux_test['id']
final_test_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_test_columnas_latlng = final_test_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 16419
1 green 114
2 blue 1259
3 cyan 25
4 yellow 2376
5 black 4236
6 brown 34256
7 orange 1315

Juntar todos los features en un solo df

Set de entrenamiento

In [54]:
clustering_train = pd.merge(final_train_columnas_basicas, final_train_columnas_superficie, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_metros_cubiertos, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_fechas, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_latlng, on='id')
# clustering_train.to_csv('./data/clustering_train_muchos.csv', index=False)
clustering_train.to_csv('./data/clustering_train_muchos_FILTRADO.csv', index=False)
clustering_train
Out[54]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 254099 0 1 0 3 1
1 53461 1 3 4 9 1
2 247984 0 6 5 3 3
3 209067 2 1 0 9 1
4 185997 0 7 2 10 3
... ... ... ... ... ... ...
236298 119879 0 1 0 4 1
236299 259178 1 0 1 4 1
236300 131932 0 7 2 10 1
236301 146867 1 6 4 2 1
236302 121958 0 6 5 10 1

236303 rows × 6 columns

Set de Testeo

In [55]:
clustering_test = pd.merge(final_test_columnas_basicas, final_test_columnas_superficie, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_metros_cubiertos, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_fechas, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_latlng, on='id')
clustering_test.to_csv('./data/clustering_test_muchos.csv', index=False)
clustering_test
Out[55]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 4941 0 0 2 7 0
1 51775 2 1 3 10 7
2 115253 5 1 5 10 0
3 299321 2 1 5 3 0
4 173570 4 1 3 2 0
... ... ... ... ... ... ...
59995 75094 1 0 2 9 0
59996 171847 4 1 3 10 6
59997 138313 4 6 5 4 6
59998 271268 4 3 5 10 6
59999 72612 4 3 1 6 5

60000 rows × 6 columns